package com.yequan.nio;

import org.apache.commons.io.FileUtils;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

/**
 * @author yq
 * @date 2020/07/02
 */
public class NioDemo {

    public static void main(String[] args) throws IOException {
        long startTime = System.currentTimeMillis();
        channelReadTest();
//        bufferReaderTest();
//        fileUtilsTest();
//        bufferTest();
//        channelByteBufferTest();
//        channelMappedBufferTest();
//        channelTransferTest();
//        copy();
        long consumeTime = System.currentTimeMillis() - startTime;
        System.out.println("耗时:" + consumeTime + " ms");
    }

    public static void copy() throws IOException {
        Path source = Paths.get("E:\\TEMP\\Demo2");
        Path target = Paths.get("E:\\TEMP\\Demo-c");
        Files.copy(source, target);
    }

    /**
     * 读取文件效率很高
     *
     * @throws IOException
     */
    public static void channelReadTest() throws IOException {
        FileChannel inChannel = FileChannel.open(Paths.get("E:\\TEMP\\read.txt"), StandardOpenOption.READ);
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        while (inChannel.read(byteBuffer) > 0) {
            byteBuffer.flip();
            System.out.println(Charset.forName("gbk").decode(byteBuffer));
            byteBuffer.clear();
        }
    }

    /**
     * 效率差
     *
     * @throws IOException
     */
    public static void bufferReaderTest() throws IOException {
        BufferedReader rdr = Files.newBufferedReader(Paths.get("E:\\TEMP\\read.txt"), Charset.forName("gbk"));
        String line = null;
        while ((line = rdr.readLine()) != null) {
            System.out.println(line);
        }
    }

    /**
     * 效率很高与channelReadTest差不多
     *
     * @throws IOException
     */
    public static void fileUtilsTest() throws IOException {
        String content = FileUtils.readFileToString(new File("E:\\TEMP\\read.txt"), "gbk");
        System.out.println(content);
    }

    /**
     * channel测试
     * 使用transfer实现文件复制
     * 零拷贝，效率最高
     *
     * @throws IOException
     */
    public static void channelTransferTest() throws IOException {
        FileChannel inChannel = FileChannel.open(Paths.get("E:\\TEMP\\4.zip"), StandardOpenOption.READ);
        FileChannel outChannel = FileChannel.open(Paths.get("E:\\TEMP\\4-t.zip"), StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE);
        outChannel.transferFrom(inChannel, 0, inChannel.size());
        outChannel.close();
        inChannel.close();
    }

    /**
     * channel测试
     * 使用内存映射实现文件复制
     * 直接缓冲区，效率高
     *
     * @throws IOException
     */
    public static void channelMappedBufferTest() throws IOException {
        FileChannel inChannel = FileChannel.open(Paths.get("E:\\TEMP\\4.zip"), StandardOpenOption.READ);
        FileChannel outChannel = FileChannel.open(Paths.get("E:\\TEMP\\4-m.zip"), StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE);
        MappedByteBuffer inMappedBuffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
        MappedByteBuffer outMappedBuffer = outChannel.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size());
        byte[] bytes = new byte[inMappedBuffer.limit()];
        inMappedBuffer.get(bytes);
        outMappedBuffer.put(bytes);
        outChannel.close();
        inChannel.close();
    }

    /**
     * channel测试
     * 使用缓冲区实现文件复制
     * 非直接缓冲区，效率较差
     *
     * @throws IOException
     */
    public static void channelByteBufferTest() throws IOException {
        FileInputStream fileInputStream = new FileInputStream("E:\\TEMP\\4.zip");
        FileOutputStream fileOutputStream = new FileOutputStream("E:\\TEMP\\4-c.zip");
        FileChannel inChannel = fileInputStream.getChannel();
        FileChannel outChannel = fileOutputStream.getChannel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        while (inChannel.read(buffer) != -1) {
            buffer.flip();
            outChannel.write(buffer);
            buffer.clear();
        }
        fileOutputStream.close();
        fileInputStream.close();
    }

    public static void bufferTest() {
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        System.out.println("初始化：limit---》》》 " + byteBuffer.limit());
        System.out.println("初始化：position---》》》 " + byteBuffer.position());
        System.out.println("初始化：mark---》》》 " + byteBuffer.mark().position());
        System.out.println("初始化：capacity---》》》 " + byteBuffer.capacity());

        String str = "java";
        byteBuffer.put(str.getBytes());

        System.out.println("写入后：limit---》》》 " + byteBuffer.limit());
        System.out.println("写入后：position---》》》 " + byteBuffer.position());
        System.out.println("写入后：mark---》》》 " + byteBuffer.mark().position());
        System.out.println("写入后：capacity---》》》 " + byteBuffer.capacity());

        byteBuffer.flip();

        System.out.println("flip后：limit---》》》 " + byteBuffer.limit());
        System.out.println("flip后：position---》》》 " + byteBuffer.position());
        System.out.println("flip后：mark---》》》 " + byteBuffer.mark().position());
        System.out.println("flip后：capacity---》》》 " + byteBuffer.capacity());

        byte[] bytes = new byte[2];
        byteBuffer.get(bytes);
        System.out.println("从buffer中读取的内容：" + new String(bytes, 0, bytes.length));

        System.out.println("读取后：limit---》》》 " + byteBuffer.limit());
        System.out.println("读取后：position---》》》 " + byteBuffer.position());
        System.out.println("读取后：mark---》》》 " + byteBuffer.mark().position());
        System.out.println("读取后：capacity---》》》 " + byteBuffer.capacity());

        byteBuffer.clear();

        System.out.println("clear后：limit---》》》 " + byteBuffer.limit());
        System.out.println("clear后：position---》》》 " + byteBuffer.position());
        System.out.println("clear后：mark---》》》 " + byteBuffer.mark().position());
        System.out.println("clear后：capacity---》》》 " + byteBuffer.capacity());

        byteBuffer.get(bytes);
        System.out.println("clear后：从buffer中读取的内容：" + new String(bytes, 0, bytes.length));
    }

}
